import React from 'react'
import { Layout, Menu, Spin, notification } from 'antd'
import io from 'socket.io-client'
import { Switch, Redirect, Route } from 'react-router-dom'
import { inject, observer } from 'mobx-react/index'
import Loadable from 'react-loadable'

import { USER_INFO } from '@/Utils/CONST'
import Event from '@/Utils/Event'
import * as eventConfig from '@/Utils/socketName'
import Tip from '@/Utils/Tip'
import { checkPermission } from '@/components/AuthComponent/utils'

import IconFont from '@/components/IconFont'
import AuthTip from '@/components/AuthTip'
import HeaderComp from '@/pages/Dashboard/common/HeaderComp'

import './basicLayout.less'

@inject('DataApprovalModel', 'BreadCrumb', 'SocketModel', 'RegionId')
@observer
export default class Dashboard extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      collapsed: false,
      loading: true,
      noSiderList: [
        '/dashboard/fabric/createOrganization',
        '/dashboard/fabric/createLeague',
        '/dashboard/resource-pool',
      ],
      userInfo: JSON.parse(localStorage.getItem(USER_INFO) || '{}'),
    }
  }

  routerList = () => {
    let routerList = [
      { pathname: '/dashboard/resource-pool', component: ResourcePool },
      { pathname: '/dashboard/fabric', component: Fabric, key: 'fabric', titleVisible: true },
      { pathname: '/dashboard/cross-chain', component: CrossChain, key: 'cross-chain', titleVisible: true },
      { pathname: '/dashboard/user', component: User, key: 'user' },
      { pathname: '/dashboard/setting', component: SettingHome, key: 'setting' },
      { pathname: '/dashboard/log', component: Log, key: 'log' },
      { pathname: '/dashboard/fabric/createOrganization', component: CreateOrganization, key: 'fabric' },
      { pathname: '/dashboard/fabric/createLeague', component: CreateLeague, key: 'fabric' },
      { pathname: '/dashboard/fabric/organizationInfo/:id', component: OrganizationManagement, key: 'fabric' },
      { pathname: '/dashboard/fabric/invite', component: InvitePage, key: 'fabric' },
      { pathname: '/dashboard/fabric/:id/:name/apply', component: InvitePage, key: 'fabric' },
      { pathname: '/dashboard/fabric/organizationInfo/:id/createPeer', component: CreatePeer, key: 'fabric' },
      { pathname: '/dashboard/fabric/leagueInfo/:id/:name', component: LeagueManagement, key: 'fabric' },
      { pathname: '/dashboard/fabric/leagueInfo/:id/:name/allBlock/:bId', component: DataList, key: 'fabric' },
      { pathname: '/dashboard/fabric/leagueInfo/:id/:name/blockDetail/:cId/:bId', component: DataDetail, key: 'fabric' },
      { pathname: '/dashboard/fabric/leagueInfo/:id/:name/allTransactions/:bId', component: DataList, key: 'fabric' },
      { pathname: '/dashboard/fabric/leagueInfo/:id/:name/transactionsDetail/:cId/:bId', component: DataDetail, key: 'fabric' },
      { pathname: '/dashboard/fabric/leagueInfo/:id/:name/createChannel', component: CreateChannel, key: 'fabric' },
      { pathname: '/dashboard/fabric/leagueInfo/:id/:name/joinChannel/:channelId/:channelName/:type', component: JoinChannel, key: 'fabric' },
      { pathname: '/dashboard/fabric/leagueInfo/:id/:name/channelOrg/:channelId/:channelName', component: ChannelOrg, key: 'fabric' },
      { pathname: '/dashboard/fabric/leagueInfo/:id/:name/policyManagement', component: PolicyManagement, key: 'fabric' },
      { pathname: '/dashboard/event', component: EventComponent, key: 'event' },
      { pathname: '/dashboard/fabric/leagueInfo/:id/:name/channelOrg/:channelId/:channelName/addNode/:peerId/:peerName', component: AddNodeToOrg, key: 'fabric' },
      { pathname: '/dashboard/permission', component: Permissions, key: 'permission' },
      { pathname: '/dashboard/cross-chain/blockList', component: CrossChainBlockList, key: 'cross-chain' },
      { pathname: '/dashboard/cross-chain/txList', component: CrossChainTxList, key: 'cross-chain' },
      { pathname: '/dashboard/cross-chain/txInfo/:hash', component: CrossChainTxInfo, key: 'cross-chain' },
      { pathname: '/dashboard/cross-chain/communicationChain/new', component: NewContractChain, key: 'cross-chain' },
      { pathname: '/dashboard/cross-chain/communicationChain/info/:id', component: ContractChainInfo, key: 'cross-chain' },
      { pathname: '/dashboard/cross-chain/contracts', component: ContractList, key: 'cross-chain' },
      { pathname: '/dashboard/cross-chain/applications', component: CrossChainApplication, key: 'cross-chain' },
    ]
    return routerList
  }

  componentDidMount() {
    // 连接socket
    // query 中的 username 时必传
    const { userInfo } = this.state
    let username = userInfo && userInfo.username
    const { SocketModel } = this.props
    let options = {
      query: {
        username,
      },
      transports: ['websocket'],
      // path: '/ws'
    }
    if (process.env.REACT_APP_SOCKET_PATH) {
      options = {
        ...options,
        path: process.env.REACT_APP_SOCKET_PATH,
      }
    }
    let socket = io('/', options)
    // 建议将socket对象通过mobx保存起来
    socket.on('connect', () => {
      const id = socket.id
      SocketModel.setSocket(socket)
      socket.on(id, msg => {
        const eventName = msg.type
        const { title, success, failed } = eventConfig[eventName] || {}
        if (title && success && failed) {
          msg.data.status === 'success' ? notification.success({
            message: title,
            description: success,
          }) : notification.error({
            message: title,
            description: failed,
          })
        }
        Event.emit(eventName, msg.data) // 发布事件
      })
    })
    socket.on('connect_error', function() {
      socket.close()
    })
  }

  getMenu = () => {
    let menu = [
      {
        name: '联盟链',
        path: '/dashboard/fabric',
        authKey: 'fabric',
        key: 'fabric',
        icon: <IconFont type="ic-nav_fabric" style={{ fontSize: '20px' }} />,
      },
      {
        name: '跨链',
        path: '/dashboard/cross-chain',
        key: 'cross-chain',
        authKey: 'cross-chain',
        icon: <IconFont type="ic-nav_quorum" style={{ fontSize: '20px' }} />,
      },
      {
        key: 'user',
        name: '用户中心',
        path: '/dashboard/user',
        authKey: 'user',
        icon: <IconFont type="ic-user" style={{ fontSize: '20px' }} />,
      },
      {
        key: 'event',
        name: '事件中心',
        path: '/dashboard/event',
        authKey: 'event',
        icon: <IconFont type="ic-shijian1" style={{ fontSize: '20px' }} />,
      },
      {
        key: 'setting',
        name: '系统设置',
        path: '/dashboard/setting',
        authKey: 'setting',
        icon: <IconFont type="ic-set" style={{ fontSize: '20px' }} />,
      },
      {
        key: 'log',
        name: '审计日志',
        path: '/dashboard/log',
        authKey: 'log',
        icon: <IconFont type="ic-shenjidaili" style={{ fontSize: '20px' }} />,
      },
    ]
    return menu.filter(v => {
      if (v.authKey) {
        return checkPermission(v.authKey)
      }
      return true
    })
  }

  onCollapse = (collapsed) => {
    this.setState({ collapsed })
  };

  unicomeList = ({ item, key, keyPath }) => {
    this.props.history.push({
      pathname: key,
    })
  }

  getCurrentMenuSelectedKeys(props) {
    const { location: { pathname }} = props || this.props
    let list = [
      '/dashboard/fabric',
      '/dashboard/cross-chain',
      '/dashboard/applicationService',
      '/dashboard/event',
      '/dashboard/setting',
      '/dashboard/log',
    ]
    let index = null
    list.map((element, count) => {
      if (pathname.includes(element)) {
        index = count
      }
    })
    let keys = list[index] ? list[index] : pathname
    this.key = keys
    return [keys]
  }

  toggle = () => {
    this.setState({
      collapsed: !this.state.collapsed,
    })
  }

  render() {
    const { collapsed, noSiderList } = this.state
    const { location: { pathname }} = this.props
    const noSider = noSiderList.includes(pathname) || pathname.includes('createPeer') || pathname.includes('exception')
    return (
      <Layout className="dashboard_layout common">
        {
          !noSider && <Sider
            className="slider"
            trigger={null}
            collapsible
            width={180}
            collapsed={collapsed}
          >
            <a href="/dashboard"><div className="menu-logo"></div></a>
            <Menu
              className="List"
              defaultSelectedKeys={this.routerList(true).length ? [this.routerList(true)[0].pathname] : ['']}
              mode="inline"
              onClick={this.unicomeList}
              selectedKeys={this.getCurrentMenuSelectedKeys()}
            >
              {
                this.getMenu().map(element => {
                  return (
                    <Menu.Item
                      icon={element.icon}
                      key={element.path}
                      className={element.key}>
                      {element.name}
                    </Menu.Item>
                  )
                })
              }
            </Menu>
            <AuthTip {...this.props} />
          </Sider>
        }
        <Layout className={'layout-header'}>
          <HeaderComp {...this.props} menuList={this.getMenu()} />
          <Content className="content">
            <Switch>
              {this.routerList().map(element => {
                return (
                  <Route
                    path={element.pathname}
                    exact
                    key={element.pathname}
                    component={ element.component}
                  />
                )
              })}
              <Route path="/dashboard" render={() => <Redirect to={this.getMenu()[0] ? (this.getMenu()[0] || {}).path : '/error/403'} />} />
              <Route path="/dashboard/*" render={() => <Redirect to={this.getMenu()[0] ? (this.getMenu()[0] || {}).path : '/error/403'} />} />
            </Switch>
          </Content>
        </Layout>
      </Layout>
    )
  }
}

const MyLoadingComponent = ({ isLoading, error }) => {
  if (isLoading) {
    return <div style={{
      width: '100%',
      height: '100%',
      position: 'absolute',
      left: '0',
      top: '0',
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'center',
    }}><Spin size="large" /></div>
  } else if (error) {
    return <Tip />
  } else {
    return null
  }
}

const { Content, Sider } = Layout

const Fabric = Loadable({
  loader: () => import('./components/Fabric'),
  loading: MyLoadingComponent,
})
const User = Loadable({
  loader: () => import('./components/User'),
  loading: MyLoadingComponent,
})
const SettingHome = Loadable({
  loader: () => import('./components/Setting'),
  loading: MyLoadingComponent,
})
const CreateOrganization = Loadable({
  loader: () => import('./components/Fabric/components/CreateOrgation'),
  loading: MyLoadingComponent,
})
const CreateLeague = Loadable({
  loader: () => import('./components/Fabric/components/CreateLeague'),
  loading: MyLoadingComponent,
})

const OrganizationManagement = Loadable({
  loader: () => import('./components/OrganizationManagement/OrganizationManagement'),
  loading: MyLoadingComponent,
})

const LeagueManagement = Loadable({
  loader: () => import('./components/LeagueInfo/index'),
  loading: MyLoadingComponent,
})

const InvitePage = Loadable({
  loader: () => import('./components/InvitePage/index'),
  loading: MyLoadingComponent,
})
const CreatePeer = Loadable({
  loader: () => import('./components/Fabric/components/CreatePeer'),
  loading: MyLoadingComponent,
})
const CreateChannel = Loadable({
  loader: () => import('./components/LeagueInfo/components/Channel/components/CreateChannel/index'),
  loading: MyLoadingComponent,
})
const JoinChannel = Loadable({
  loader: () => import('./components/LeagueInfo/components/Channel/components/JoinChannel/index'),
  loading: MyLoadingComponent,
})
const AddNodeToOrg = Loadable({
  loader: () => import('./components/LeagueInfo/components/Channel/components/AddNode/index'),
  loading: MyLoadingComponent,
})
const ChannelOrg = Loadable({
  loader: () => import('./components/LeagueInfo/components/Channel/components/ChannelOrg/index'),
  loading: MyLoadingComponent,
})

const EventComponent = Loadable({
  loader: () => import('./components/Event'),
  loading: MyLoadingComponent,
})

const DataList = Loadable({
  loader: () => import('./components/LeagueInfo/components/BlockchainBrowser/AllList'),
  loading: MyLoadingComponent,
})

const DataDetail = Loadable({
  loader: () => import('./components/LeagueInfo/components/BlockchainBrowser/DataDetail'),
  loading: MyLoadingComponent,
})

const PolicyManagement = Loadable({
  loader: () => import('./components/LeagueInfo/components/Chaincode/PolicyManagement'),
  loading: MyLoadingComponent,
})
const Permissions = Loadable({
  loader: () => import('./components/Inner/Permission'),
  loading: MyLoadingComponent,
})
const Log = Loadable({
  loader: () => import('./components/Log'),
  loading: MyLoadingComponent,
})

const ResourcePool = Loadable({
  loader: () => import('./components/ResourcePool'),
  loading: MyLoadingComponent,
})
const CrossChain = Loadable({
  loader: () => import('./components/CrossChain/index'),
  loading: MyLoadingComponent,
})
const CrossChainBlockList = Loadable({
  loader: () => import('./components/CrossChain/pages/BlockList/index'),
  loading: MyLoadingComponent,
})
const CrossChainTxList = Loadable({
  loader: () => import('./components/CrossChain/pages/Transaction/List/index'),
  loading: MyLoadingComponent,
})
const CrossChainTxInfo = Loadable({
  loader: () => import('./components/CrossChain/pages/Transaction/Info/index'),
  loading: MyLoadingComponent,
})
const NewContractChain = Loadable({
  loader: () => import('./components/CrossChain/pages/CommunicationChain/New/index'),
  loading: MyLoadingComponent,
})
const ContractChainInfo = Loadable({
  loader: () => import('./components/CrossChain/pages/CommunicationChain/Info/index'),
  loading: MyLoadingComponent,
})
const ContractList = Loadable({
  loader: () => import('./components/CrossChain/pages/Contract/List/index'),
  loading: MyLoadingComponent,
})
const CrossChainApplication = Loadable({
  loader: () => import('./components/CrossChain/pages/CrossChainApplication/index'),
  loading: MyLoadingComponent,
})
